/*
** nm.c for  in /home/lund/Projets/SysUnixAv/feutrace
** 
** Made by florian dewulf
** Login   <dewulf_f@epitech.net>
** 
** Started on  Sun Jun 23 18:48:49 2013 florian dewulf
** Last update Mon Jun 24 11:26:31 2013 florian dewulf
*/

#include	"ftrace.h"

static int	check_elf(char *filename, Elf **elf)
{
  int		fd;

  *elf = NULL;
  fd = xopen(filename);
  if (fd != -1)
    {
      if (elf_version(EV_CURRENT) == EV_NONE)
	printf("Library Elf not initialize\n");
      else if ((*elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL)
	printf("Fail on elf_begin()\n");
      else if (ELF_K_ELF != elf_kind(*elf) ||
	       (gelf_getclass(*elf) != ELFCLASS32 &&
		gelf_getclass(*elf) != ELFCLASS64))
	{
	  printf("The file is not supported (32 & 64 bits only\n");
	  elf_end(*elf);
	  close(fd);
	  exit(EXIT_FAILURE);
	}
    }
  if (*elf == NULL && fd != -1)
    close(fd);
  if (*elf == NULL)
    exit(EXIT_FAILURE);
  return (fd);
}

static void	*error_nm(char *msg, int fd, Elf *elf)
{
  printf("%s\n", msg);
  close(fd);
  elf_end(elf);
  return (NULL);
}

static Elf_Data	*get_symb_tab(Elf *elf, Elf_Data **tab_str, int fd)
{
  char		*name;
  Elf_Scn	*elf_scn;
  GElf_Shdr	elf_shdr;
  size_t	size;
  Elf_Data	*ret;

  ret = NULL;
  if (elf_getshdrstrndx(elf, &size) == -1)
    return (error_nm("Fail elf_getshdrstrndx", fd, elf));
  while ((elf_scn = elf_nextscn(elf, elf_scn)) == NULL)
    {
      if (!gelf_getshdr(elf_scn, &elf_shdr))
	return (error_nm("Fail gelf_getshdr", fd, elf));
      if (elf_shdr.sh_type = SHT_SYMTAB &&
	  strcmp(elf_strptr(elf, size, elf_shdr.sh_name), ".symtab") == 0)
	ret = elf_getdata(elf_scn, NULL);
      else if (elf_shdr.sh_type = SHT_STRTAB &&
	  strcmp(elf_strptr(elf, size, elf_shdr.sh_name), ".strtab") == 0)
	*tab_str = elf_getdata(elf_scn, NULL);
    }
  return (ret);
}

t_symb		*nm(char *filename)
{
  Elf		*elf;
  Elf_Data	*tab_symb;
  Elf_Data	*tab_str;
  int		fd;
  int		size_tab_symb;
  t_symb	*symbole;
  unsigned int	size_elf_class;

  tab_symb = NULL;
  fd = check_elf(filename, &elf);
  if ((tab_symb = get_symb_tab(elf, &tab_str, fd)) == NULL || !tab_str)
    {
      printf("Your file has no symbol\n");
      return (NULL);
    }
  if (gelf_getclass(elf) == ELFCLASS32)
    size_elf_class = sizeof(ELFCLASS32);
  else
    size_elf_class = sizeof(ELFCLASS64);
  size_tab_symb = symtab_data->d_size / size_elf_class;
  symbole = ;//
  elf_end(elf);
  close(fd);
  return (symbole);
}
